﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.AnalysisTools;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using ESRI.ArcGIS.Geometry;

namespace PlanningGIS.ArcGIS
{
    /// <summary>
    /// 
    /// </summary>
    public static class FieldHelper
    {
        #region 字段相关函数

        /// <summary>
        /// 为要素类添加一个字段
        /// </summary>
        /// <param name="featCls"></param>
        /// <param name="fieldName"></param>
        /// <param name="fieldType"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static bool AddFieldToFeatureClass(IFeatureClass featCls, string fieldName, esriFieldType fieldType, int length = 50)
        {
            if (featCls.FindField(fieldName) != -1) return true;
            try
            {
                IFieldEdit fieldEdit = new FieldClass();
                fieldEdit.Name_2 = fieldName;
                fieldEdit.Type_2 = fieldType;
                fieldEdit.Length_2 = length;
                featCls.AddField(fieldEdit);
                return true;
            }
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// 把要素类的字段加载到combox,在符号化界面中经常用到
        /// </summary>
        /// <param name="pFeatCls">要素类</param>
        /// <param name="combox1">列表框</param>
        [Obsolete("已废弃")]
        public static void AddFieldToCombo(IFeatureClass pFeatCls, ComboBox combox1)
        {
            IFields pFields = pFeatCls.Fields;

            for (int i = 0; i < pFields.FieldCount; i++)
            {
                IField pField = pFields.get_Field(i);
                //其它字段暂不加载
                switch (pField.Type)
                {
                    case esriFieldType.esriFieldTypeString:
                    case esriFieldType.esriFieldTypeDouble:
                    case esriFieldType.esriFieldTypeSingle:
                    case esriFieldType.esriFieldTypeSmallInteger:
                    case esriFieldType.esriFieldTypeInteger:
                        combox1.Items.Add(pField.Name);
                        break;
                }
            }
            if (combox1.Items.Count > 0)
            {
                combox1.SelectedIndex = 0;
            }
        }

        #endregion

        /// <summary>
        /// 通过IQueryDef接口获取字段唯一值（效率较高，且更稳定）,仅gdb中矢量图层都可以使用
        /// </summary>
        /// <param name="featureclass">要素类</param>
        /// <param name="fieldName">字段名称</param>
        /// <param name="hasStr">是否包含字符串标识，即首尾添加'符号</param>
        /// <returns></returns>
        public static ArrayList GetUniqueValuesByQueryDef(IFeatureClass featureclass, string fieldName, bool hasStr = false)
        {
            ArrayList values = new ArrayList();
            IFeatureWorkspace featWs = (featureclass as IDataset).Workspace as IFeatureWorkspace;
            IQueryDef pQueryDef = featWs.CreateQueryDef();
            pQueryDef.Tables = (featureclass as IDataset).Name;
            pQueryDef.SubFields = "DISTINCT " + fieldName;
            ICursor pCursor = pQueryDef.Evaluate();
            IRow pRow = pCursor.NextRow();
            while (pRow != null)
            {
                if (hasStr) values.Add(string.Format("'{0}'", pRow.get_Value(0)));
                else values.Add(pRow.get_Value(0));
                pRow = pCursor.NextRow();
            }
            Marshal.ReleaseComObject(pCursor);
            return values;
        }

        /// <summary>
        /// 得到要素类某字段的唯一值,shp和gdb中矢量图层都可以使用
        /// </summary>
        /// <param name="pFeatureClass">要素类（shp和gdb中要素类）</param>
        /// <param name="strFld">指定要得到唯一值的字段</param>
        /// <returns>唯一值字符数据</returns>
        public static List<string> GetUniqueValueByDataStatistics(IFeatureClass pFeatureClass, string strFld)
        {
            int indexFld = pFeatureClass.FindField(strFld);
            if (indexFld == -1)
            {
                Util.Log.LogHelper.WriteErrorText("矢量图层中不存在字段" + strFld);
                return new List<string>();
            }
            IQueryFilter pQueryF = new QueryFilterClass();
            pQueryF.SubFields = strFld;

            //得到IFeatureCursor游标
            IFeatureCursor pCursor = pFeatureClass.Search(pQueryF, false);
            //coClass对象实例生成
            IDataStatistics pData = new DataStatisticsClass();
            pData.Field = strFld;
            pData.Cursor = pCursor as ICursor;

            //枚举唯一值
            IEnumerator pEnumVar = pData.UniqueValues;


            //字符数组
            List<string> fieldunique = new List<string>();
            pEnumVar.Reset();

            while (pEnumVar.MoveNext())
            {
                fieldunique.Add(pEnumVar.Current.ToString());
            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(pCursor);
            return fieldunique;
        }
        

        /// <summary>
        /// 将默认的OBJECTID、SHAPE添加到字段中
        /// </summary>
        /// <param name="fields"></param>
        /// <param name="geometryType"></param>
        /// <param name="spatialReference"></param>
        /// <returns></returns>
        public static void AddDefaultFields(this IFields fields, esriGeometryType geometryType, ISpatialReference spatialReference = null)
        {
            if (fields == null) fields = new Fields();
            IField field = new Field();
            IFieldsEdit fieldsEdit = fields as IFieldsEdit;
            IFieldEdit fieldEdit = field as IFieldEdit;
            if (fields.FindField("OBJECTID") < 0)
            {
                fieldEdit.Name_2 = "OBJECTID";
                fieldEdit.Type_2 = esriFieldType.esriFieldTypeOID;
                fieldEdit.IsNullable_2 = false;
                fieldEdit.Required_2 = false;
                fieldsEdit.AddField(field);
            }
            field = new Field();
            fieldEdit = field as IFieldEdit;
            IGeometryDef geoDef = new GeometryDefClass();
            IGeometryDefEdit geoDefEdit = (IGeometryDefEdit)geoDef;
            geoDefEdit.AvgNumPoints_2 = 5;
            geoDefEdit.GeometryType_2 = geometryType;
            geoDefEdit.GridCount_2 = 1;
            geoDefEdit.HasM_2 = false;
            geoDefEdit.HasZ_2 = false;
            geoDefEdit.SpatialReference_2 = spatialReference;
            fieldEdit.Name_2 = "SHAPE";
            fieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
            fieldEdit.GeometryDef_2 = geoDef;
            fieldEdit.IsNullable_2 = true;
            fieldEdit.Required_2 = true;
            fieldsEdit.AddField(field);
        }
    }
}
